#pragma once
#include <d3d9.h>
#pragma comment(lib, "d3d9.lib")
#include <d3dx9.h>
#pragma comment(lib, "d3dx9.lib")
#include <DxErr.h>
#pragma comment(lib, "dxerr.lib")

#include <sstream>
#include <assert.h>
#include <string>
#include <Windows.h>
#include <sstream>

#include "Piece.h"
#include "DirectInput.h"
#include "Vector.hpp"
#include"Globals.h"
#include "Menu.h"



// struct for camera vectors
struct d3dCamera
{
	
	D3DXVECTOR3 eyePos;
	D3DXVECTOR3 lookAt;
	D3DXVECTOR3	upVec;
};


struct backGround
{
	IDirect3DTexture9*			m_texture;
	D3DSURFACE_DESC             m_Desc;
	D3DXVECTOR2                 m_position;
	XYZ							m_scale;  
   
	D3DXVECTOR3                 m_center;
};

//Will be 1 mesh for each piece
//holds material for mesh
//holds texture
//holds mesh
struct PlayerSwitch
{
	IDirect3DTexture9* m_texture;
	XYZ m_position;
	XYZ m_scale;
	D3DSURFACE_DESC m_desc;
	XYZ m_center;

};
struct D3DXMeshInfo
{

	D3DXMATRIX					m_pieceMatRotate;
	D3DXMATRIX					m_pieceMatScale;
	D3DXMATRIX					m_pieceMatTranslate;
	const char* msz_fileName;						//names of .x files
	LPD3DXMESH m_meshPiece;							// the mesh info
	D3DMATERIAL9* mp_pieceMaterial;					// define the material object
	LPDIRECT3DTEXTURE9* mp_pieceTexture;			// a pointer to a texture
	DWORD mdw_pieceNumMaterials;
	LPD3DXBUFFER m_bufPieceMaterial;
	D3DXMATERIAL* m_pieceTempMaterials;
	 char* msz_texturefileName;						//names of .x files
	D3DXMeshInfo();
	
    void drawMesh(LPDIRECT3DDEVICE9 &a_dev);		// draws the meshes
	void loadMaterials(LPDIRECT3DDEVICE9 &a_dev);
};

// singleton graphics engine
class Graphics
{
private:
	Graphics();							// private ctor allows this class to be a singleton

	// member variables

	LPDIRECT3DDEVICE9			m_pD3DDevice;						// the main device of the Graphics class
	IDirect3DTexture9*          m_menuTex;                          // the texture of the menu sprite
	D3DSURFACE_DESC             m_menuDesc;                         // texture description
	LPD3DXSPRITE				m_pD3DSprite;						// sprite handler
	LPDIRECT3DTEXTURE9			m_pButtonTexture;
	backGround                  m_MenuTexture;						// menu texture
	IDirect3DTexture9*          m_PlayerSwitch;
	char*						m_mszCardTextureFileName[g_inumOfDifferentCards];		// array with the file names
	LPDIRECT3DTEXTURE9			m_CardTextures[g_inumOfDifferentCards];					// array of textures for the cards
	HWND						m_hWnd;								// a copy of hWnd from main.cpp
	Dimensions					m_dimScreen;						// a copy of the screen dimensions
	bool						m_bWindowed;						// false means the window is fullscreen
	D3DPRESENT_PARAMETERS		m_D3Dpp;							// present parameters
	bool						m_bInitialized;
	D3DLIGHT9					m_DefaultLight;
	D3DLIGHT9					m_PieceLight;
	RECT                        m_rCardLoc[14];
	int                         m_iCardNum[g_inumOfDifferentCards];

	d3dCamera					m_Camera;							// holds the camera related vectors
	PlayerSwitch                m_sPause;                            // Pause Screen Structure
	ID3DXFont*					m_pD3DFont;							// the font handler
	RECT						m_rTextBox;
	std::stringstream			m_FontStream;

	// matrices used for camera
	D3DXMATRIX					m_matPerspective;
	D3DXMATRIX					m_matView;

	// matrices used for world matrix computations
	D3DXMATRIX					m_matWorld;
	D3DXMATRIX					m_matScale;
	D3DXMATRIX					m_matTrans;
	D3DXMATRIX					m_matRot;

	// mesh and texture info for all drawable objects
	D3DXMeshInfo			DrawInfo[NUM_MESHES];

	// subfunctions of Init()
	bool SetupDevice(HWND hWnd);
	bool SetupCamera();
	bool SetupFont();
	bool SetupMeshes();
	bool SetupLight();
	bool SetupMaterials();
	void MoveCameraTo(D3DXVECTOR3 newPos);
	void UpdateCamera();

	void RenderFont(BaseObject*);

public:
	backGround getBG(){return m_MenuTexture;}
	bool Init(HWND hWnd);
	static inline Graphics* Engine()			// function used to access the singleton
	{ static Graphics g; return &g; }	
  
	void LoadMeshFile(D3DXMeshInfo &meshInfo);	//pass in D3DMeshInfo to draw everything
	bool RenderMenu();
	bool RenderGame(Vector<BaseObject*>, bool);

	~Graphics();
};

